package jdos.ints;

import jdos.Dosbox;
import jdos.hardware.*;
import jdos.misc.Log;
import jdos.types.LogSeverities;
import jdos.types.LogTypes;
import jdos.util.Ptr;

public class Int10_modes {
    static public final int _EGA_HALF_CLOCK		=0x0001;
    static public final int  _EGA_LINE_DOUBLE	=0x0002;
    static public final int  _VGA_PIXEL_DOUBLE	=0x0004;

    static public final int  SEQ_REGS =0x05;
    static public final int  GFX_REGS =0x09;
    static public final int  ATT_REGS =0x15;

    public static Int10.VideoModeBlock ModeList_VGA[]={
            /*                           mode  ,    type     ,sw  ,sh  ,tw ,th ,cw,ch ,pt,pstart  ,plength,vde special flags */
              new Int10.VideoModeBlock( 0x003  ,VGA.M_TEXT   ,640 ,480 ,80 ,25 ,8 ,16 ,8 ,0xB8000 ,0x1000 ,480),
              new Int10.VideoModeBlock( 0x012  ,VGA.M_EGA    ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,480),


    };

    public static Int10.VideoModeBlock CurMode = ModeList_VGA[0];

	private static boolean SetCurMode(int mode) {
		for (int i = 0; i < ModeList_VGA.length; i++) {
			if (ModeList_VGA[i].mode == mode) {
				CurMode = ModeList_VGA[i];
				return true;
			}
		}
		CurMode = ModeList_VGA[0];
		return false;
	}

    private static void FinishSetMode() {

        /*Bit16u*/int seg = 0xb800;
        for (/*Bit16u*/int ct=0;ct<16*1024;ct++) Memory.real_writew(seg,ct*2,0x0720);
        
        /* Setup the BIOS */
        Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_CURRENT_MODE,CurMode.mode);
        Memory.real_writew(Int10.BIOSMEM_SEG,Int10.BIOSMEM_NB_COLS,CurMode.twidth);
        Memory.real_writew(Int10.BIOSMEM_SEG,Int10.BIOSMEM_PAGE_SIZE,CurMode.plength);
        Memory.real_writew(Int10.BIOSMEM_SEG,Int10.BIOSMEM_CRTC_ADDRESS, 0x3d4);
        Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_NB_ROWS,(CurMode.theight-1));
        Memory.real_writew(Int10.BIOSMEM_SEG,Int10.BIOSMEM_CHAR_HEIGHT,CurMode.cheight);
        Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_VIDEO_CTL,(0x60));
        Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_SWITCHES,0x09);

        // this is an index into the dcc table:
        //if (Dosbox.IS_VGA_ARCH())
        Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_DCC_INDEX,0x0b);
        Memory.real_writed(Int10.BIOSMEM_SEG,Int10.BIOSMEM_VS_POINTER,Int10.int10.rom.video_save_pointers);

        // Set cursor shape
        if (CurMode.type==VGA.M_TEXT) {
            Int10_char.INT10_SetCursorShape((short)0x06,(short)07);
        }
        // Set cursor pos for page 0..7
        //for (/*Bit8u*/int ct=0;ct<8;ct++) Int10_char.INT10_SetCursorPos((short)0,(short)0,(short)ct);
        // Set active page 0
        Int10_char.INT10_SetActivePage((short)0);
        /* Set some interrupt vectors */
        switch (CurMode.cheight) {
        case 8:Memory.RealSetVec(0x43,Int10.int10.rom.font_8_first);break;
        case 14:Memory.RealSetVec(0x43,Int10.int10.rom.font_14);break;
        case 16:Memory.RealSetVec(0x43,Int10.int10.rom.font_16);break;
        }
        /* Tell mouse resolution change */
        Mouse.Mouse_NewVideoMode();
    }

public static boolean INT10_SetVideoMode(/*Bit16u*/int mode) {
	System.out.println("vgaMode:"+mode);

	/*Bitu*/int i;

	if (Log.level<=LogSeverities.LOG_NORMAL) Log.log(LogTypes.LOG_INT10,LogSeverities.LOG_NORMAL,"Set Video Mode "+Integer.toString(mode,16));
	//if (!Dosbox.IS_EGAVGA_ARCH()) return INT10_SetVideoMode_OTHER(mode,clearmem);

	/* First read mode setup settings from bios area */
//	Bit8u video_ctl=Memory.real_readb(Int10.BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
//	Bit8u vga_switches=Memory.real_readb(Int10.BIOSMEM_SEG,BIOSMEM_SWITCHES);
	///*Bit8u*/int modeset_ctl=Memory.real_readb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_MODESET_CTL);
	//System.out.println("modeset_ctl:"+modeset_ctl);

	SetCurMode(mode);

	/* Setup the VGA to the correct mode */


	/* Setup MISC Output Register */
	/*Bit8u*/int misc_output=0x2 | 0x1;

	if ((CurMode.type==VGA.M_TEXT) && (CurMode.cwidth==9)) {
		// 28MHz (16MHz EGA) clock for 9-pixel wide chars
		misc_output|=0x4;
	}

	switch (CurMode.vdispend) {
	case 400:
		misc_output|=0x60;
		break;
	case 480:
		misc_output|=0xe0;
		break;
	default:
		misc_output|=0x60;
	}
	IoHandler.IO_Write(0x3c2,misc_output);		//Setup for 3b4 or 3d4

    VGA.vga.seq.map_mask= 0x0f;
    {
        /*Bit8u*/int font1=(0 & 0x3) << 1;
        //if (Dosbox.IS_VGA_ARCH())
        font1|=(0 & 0x10) >> 4;
        VGA.vga.draw.font_tables[0]=new Ptr(VGA.vga.draw.font,font1*8*1024);
        /*Bit8u*/int font2=((0 & 0xc) >> 1);
        //if (Dosbox.IS_VGA_ARCH())
        font2|=(0 & 0x20) >> 5;
        VGA.vga.draw.font_tables[1]=new Ptr(VGA.vga.draw.font,font2*8*1024);
    }
    
    //VGA_memory.VGA_SetupHandlers();
    
    
	/* Vertical Display End */
	//IoHandler.IO_Write(crtc_base,0x12);IoHandler.IO_Write(crtc_base+1,CurMode.vdispend-1);
	//VGA_crtc.ctrc1w(0x12, CurMode.vdispend-1);


	/* Write Misc Output */
	IoHandler.IO_Write(0x3c2,misc_output);
	/* Program Graphics controller */
	/*Bit8u*/short[] gfx_data = new short[GFX_REGS];
	//memset(gfx_data,0,GFX_REGS);
	gfx_data[0x7]=0xf;				/* Color don't care */
	gfx_data[0x8]=0xff;				/* BitMask */
	switch (CurMode.type) {
	case VGA.M_TEXT:
		gfx_data[0x5]|=0x10;		//Odd-Even Mode
		break;
	case VGA.M_EGA:
		break;
	}
	for (/*Bit8u*/short ct=0;ct<GFX_REGS;ct++) {
		if(ct!=5 && ct!=6) {
		IoHandler.IO_Write(0x3ce,ct);
		IoHandler.IO_Write(0x3cf,gfx_data[ct]);
		}
	}
	
    VGA.vga.config.write_mode=(short)(gfx_data[0x5] & 3);
    
    
	

	/* Setup the DAC */
	//IoHandler.IO_Write(0x3c8,0);
    for (i=0;i<16;i++) {
        //IoHandler.IO_Write(0x3c9,text_palette2[i][0]);
        //IoHandler.IO_Write(0x3c9,text_palette2[i][1]);
        //IoHandler.IO_Write(0x3c9,text_palette2[i][2]);
    	int r = Int10_pal.text_palette[Int10_pal.table[i]][0];
    	int g = Int10_pal.text_palette[Int10_pal.table[i]][1];
    	int b = Int10_pal.text_palette[Int10_pal.table[i]][2];
        VGA_dac.setPal(i, r, g, b);
    }

	//if (Dosbox.IS_VGA_ARCH()) {
	/* check if gray scale summing is enabled */
//	if ((Memory.real_readb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_MODESET_CTL) & 2)!=0) {
//		Int10_pal.INT10_PerformGrayScaleSumming(0,256);
//	}
	//}
	switch (CurMode.type) {
	case VGA.M_TEXT:
		Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_CURRENT_MSR,0x29);
		break;
	}
	// disabled, has to be set in bios.cpp exclusively
//	Memory.real_writeb(Int10.BIOSMEM_SEG,Int10.BIOSMEM_INITIAL_MODE,feature);


	FinishSetMode();

	/* Set vga attrib register into defined state */
//	IoHandler.IO_Read(0x3da);
//	IoHandler.IO_Write(0x3c0,0x20);

	/* Load text mode font */
	if (CurMode.type==VGA.M_TEXT) {
		Int10_memory.INT10_LoadFont(Memory.Real2Phys(Int10.int10.rom.font_16),16);
	}

	return true;
}

}
